﻿/*
 * KLF Headless Browser
 * Written by Kris Oye <kristianoye@gmail.com>
 * Copyright (C) 2011-2012.  All rights reserved.
 */
namespace KLF.Lib.Browser.DOM.HTML
{
    #region Using Statements

    using System;
    using KLF.Lib.Browser.DOM.Interface;
    
    #endregion

    /// <summary>
    /// Inline subwindows. See the IFRAME element definition in HTML 4.01.
    /// </summary>
    public class HTMLFrameElement : HTMLElement, ILoadableContent
    {
        #region Properties

        /// <summary>
        /// The internal reference to any loaded document
        /// </summary>
        internal Document _contentDocument { get; set; }

        /// <summary>
        /// Starts false but turns true when the document attempts to load.
        /// </summary>
        public bool HasLoaded { get; set; }

        #endregion

        #region Constructors

        internal HTMLFrameElement(Document owner)
            : base(owner, HTMLConstants.HTML_TAG_FRAME)
        {
            _contentDocument = null;
            HasLoaded = false;
        }

        #endregion

        #region DOM Level 2 HTML Compliance

        /// <summary>
        /// The document this frame contains, if there is any and it is 
        /// available, or null otherwise.
        /// </summary>
        public Document contentDocument
        {
            get
            {
                if (!HasLoaded)
                    loadDocument();
                return _contentDocument;
            }
        }

        /// <summary>
        /// Request frame borders. See the frameborder attribute definition in HTML 4.01.
        /// </summary>
        public string frameBorder
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_FRAMEBORDER);
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    removeAttribute(HTMLConstants.HTML_ATT_FRAMEBORDER);
                else if (value.Equals("1") || value.Equals("0"))
                    setAttribute(HTMLConstants.HTML_ATT_FRAMEBORDER, value);
                else
                    Owner.AddStrict("HTMLFrameElement.frameBorder must be '1' or '0', not '{0}'", value);
            }
        }

        /// <summary>
        /// URI [IETF RFC 2396] designating a long description of this image or frame. 
        /// 
        /// See the longdesc attribute definition in HTML 4.01.
        /// </summary>
        public string longDesc
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_LONGDESC);
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    removeAttribute(HTMLConstants.HTML_ATT_LONGDESC);
                else
                    setAttribute(HTMLConstants.HTML_ATT_LONGDESC, value);
            }
        }

        /// <summary>
        /// Frame margin height, in pixels. See the marginheight attribute 
        /// definition in HTML 4.01.
        /// </summary>
        public string marginHeight
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_MARGINHEIGHT);
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    removeAttribute(HTMLConstants.HTML_ATT_MARGINHEIGHT);
                else
                    setAttribute(HTMLConstants.HTML_ATT_MARGINHEIGHT, value);
            }
        }

        /// <summary>
        /// Frame margin width, in pixels. See the marginwidth attribute 
        /// definition in HTML 4.01.
        /// </summary>
        public string marginWidth
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_MARGINWIDTH);
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    removeAttribute(HTMLConstants.HTML_ATT_MARGINWIDTH);
                else
                    setAttribute(HTMLConstants.HTML_ATT_MARGINWIDTH, value);
            }
        }

        /// <summary>
        /// The frame name (object of the target attribute). See the name 
        /// attribute definition in HTML 4.01.
        /// </summary>
        public string name
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_NAME);
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    removeAttribute(HTMLConstants.HTML_ATT_NAME);
                else
                    setAttribute(HTMLConstants.HTML_ATT_NAME, value);
            }
        }

        /// <summary>
        /// When true, forbid user from resizing frame. See the noresize 
        /// attribute definition in HTML 4.01.
        /// </summary>
        public bool noResize
        {
            get
            {
                return getAttributeAsType<bool>(HTMLConstants.HTML_ATT_NORESIZE, false);
            }
            set
            {
                setAttributeAsType<bool>(HTMLConstants.HTML_ATT_NORESIZE, value);
            }
        }

        /// <summary>
        /// Specify whether or not the frame should have scrollbars. 
        /// 
        /// See the scrolling attribute definition in HTML 4.01.
        /// </summary>
        public string scrolling
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_SCROLLING);
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    removeAttribute(HTMLConstants.HTML_ATT_SCROLLING);
                else
                    setAttribute(HTMLConstants.HTML_ATT_SCROLLING, value);
            }
        }

        /// <summary>
        /// A URI [IETF RFC 2396] designating the initial frame contents. 
        /// 
        /// See the src attribute definition in HTML 4.01.
        /// </summary>
        public string src
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_SRC);
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    removeAttribute(HTMLConstants.HTML_ATT_SRC);
                else
                    setAttribute(HTMLConstants.HTML_ATT_SRC, value);
            }
        }

        #endregion

        #region DOM Non-Standard Methods

        /// <summary>
        /// Loads the frame document from source.
        /// </summary>
        internal void loadDocument()
        {
            try
            {
                if (!HasLoaded && !String.IsNullOrEmpty(src))
                {
                    HasLoaded = true;
                }
            }
            catch (Exception ex)
            {
                Owner.AddError("Failed to load frame document: {0}", ex.Message);
            }
        }

        #endregion
    }
}
